0%

Golang PutUvarint Uvarint

bigcache库的时候,注意到存放数据用的是PutUvarint、Uvarint,那这两个方法是做什么的呢?

PutUvarint

源码及注释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// PutUvarint encodes a uint64 into buf and returns the number of bytes written.
// If the buffer is too small, PutUvarint will panic.
// PutVarint 将 int64 编码为 buf 并返回写入的字节数。如果缓冲区太小,PutVarint 会panic。
func PutUvarint(buf []byte, x uint64) int {
i := 0
// 0x80 128
for x >= 0x80 {
buf[i] = byte(x) | 0x80
// 右移7位,然后将右移后的值,赋值给x
x >>= 7
i++
}
buf[i] = byte(x)
return i + 1
}

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import (
"encoding/binary"
"fmt"
)

func main() {
buf := make([]byte, binary.MaxVarintLen64)

for _, x := range []int64{-65, -64, -2, -1, 0, 1, 2, 63, 64} {
n := binary.PutVarint(buf, x)
fmt.Printf("%x\n", buf[:n])
}
}

输出结果

1
2
3
4
5
6
7
8
9
10
11
8101
7f
03
01
00
02
04
7e
8001

Program exited.

https://go.dev/play/p/yRUoUooVrHm

Uvarint

源码及注释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Uvarint decodes a uint64 from buf and returns that value and the
// number of bytes read (> 0). If an error occurred, the value is 0
// and the number of bytes n is <= 0 meaning:
//
// n == 0: buf too small
// n < 0: value larger than 64 bits (overflow)
// and -n is the number of bytes read
// Uvarint 从 buf 解码 uint64 并返回该值和读取的字节数(> 0)。如果发生错误,则该值为0,并且字节数n <= 0意味着:
// n == 0:buf太小了
// n <0:大于64位的值(溢出)
// 和-n是读取的字节数
func Uvarint(buf []byte) (uint64, int) {
var x uint64
var s uint
for i, b := range buf {
// MaxVarintLen64 10
if i == MaxVarintLen64 {
// Catch byte reads past MaxVarintLen64.
// See issue https://golang.org/issues/41185
return 0, -(i + 1) // overflow
}
// 0x80 128
if b < 0x80 {
if i == MaxVarintLen64-1 && b > 1 {
return 0, -(i + 1) // overflow
}
return x | uint64(b)<<s, i + 1
}
// 0x7f 127
x |= uint64(b&0x7f) << s
s += 7
}
return 0, 0
}

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main

import (
"encoding/binary"
"fmt"
)

func main() {
inputs := [][]byte{
[]byte{0x01}, //1
[]byte{0x02}, //2
[]byte{0x7f}, //127
[]byte{0x80, 0x01}, //128,1
[]byte{0xff, 0x01}, //255,1
[]byte{0x80, 0x02}, //128,2
[]byte{0x80, 0x03}, //128,3
}
for _, b := range inputs {
x, n := binary.Uvarint(b)
if n != len(b) {
fmt.Println("Uvarint did not consume all of in")
}
fmt.Println(x)
}
}

输出结果

1
2
3
4
5
6
7
8
9
1
2
127
128
255
256
384

Program exited.

https://go.dev/play/p/df572cFK6Im

在线16进制转10进制:https://jisuan5.com/hexadecimal-to-decimal/
参考文章:https://cloud.tencent.com/developer/section/1141534

欢迎关注我的其它发布渠道